/**
在类中实现右值引用通常涉及到两个方面：
1. 移动构造函数
2. 移动赋值运算符
移动构造函数用于构造一个新对象，同时“移动”原对象的资源到新对象，而不是复制资源。
移动赋值运算符用于将一个对象的资源“移动”到另一个对象，同样不需要复制资源。

*/
#include<iostream>
#include<string>
#include <stdlib.h>
#include <utility> // for std::move

class MyClass {
public:
    // 默认构造函数
    MyClass() : data(nullptr),id(0) {
        id = rand()%899 + 100;
        std::cout << id <<" Default constructor called."<< std::endl;
    }

    // 构造函数，接受一个字符串
    MyClass(const std::string& str) : data(new std::string(str)),id(10) {
        id = rand()%899 + 100;
        std::cout << id << " Constructor called with string: " << *data<< std::endl;
    }

    // 移动构造函数
    MyClass(MyClass&& other) noexcept : data(other.data) {
        std::cout << "Move constructor called."<< std::endl;
        other.data = nullptr; // 将原对象的指针置空，避免析构时重复释放资源
    }

    // 移动赋值运算符
    MyClass& operator=(MyClass&& other) noexcept {
        std::cout << id << " Move assignment operator called."<< std::endl;
        if (this != &other) {
            delete data; // 释放当前对象的资源
            data = other.data; // 将原对象的资源“移动”到当前对象
            other.data = nullptr; // 将原对象的指针置空，避免析构时重复释放资源
        }
        return *this;
    }

    // 析构函数
    ~MyClass() {
        std::cout << id << " Destructor called."<< std::endl;
        delete data;
    }

    void foo(){
        std::cout << id << " test foo: " << data << std::endl;
    }

private:
    std::string* data;
    int id;
};

int main() {
    MyClass obj1("Hello, world!");
    MyClass obj2(std::move(obj1)); // 调用移动构造函数

    MyClass obj3;
    obj3 = std::move(obj2); // 调用移动赋值运算符

    obj1.foo();
    obj2.foo();
    obj3.foo();

    return 0;
}
/*
使用gdb 查看obj1,obj2,obj3 的id,data变化过程

最终内存值:
obj1: id = 0, data = nullptr
obj2: id = 10, data = nullptr
obj3: id = 10, data = "Hello, world!"
 */